/* eslint-disable react/forbid-prop-types */
import Taro from '@tarojs/taro'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { ScrollView, View, Text } from '@tarojs/components'
import { NoContentEmpty } from '@COMPONENTS/Empty'
import { getWebRealPx, convertPx, isIOSWeb } from '@UTILS/common'
import { LIST_PAGE_STATUS, TEXT_MAP } from '@CONSTANTS/app'
import './CommonList.scss'

const getStyle = height => ({ height: convertPx(height) })

class CommonList extends Component {
  state = {
    height: 500,
  }

  componentDidMount() {
    const { listHeaderHeight } = this.props
    Taro.getSystemInfo({
      success: res => {
        this.setState({
          height: res.windowHeight - getWebRealPx(listHeaderHeight) - (isIOSWeb() ? 34 : 0)
        })
      }
    })
  }

  componentDidUpdate(prevProps) {
    const { listHeaderHeight } = this.props
    if (prevProps.listHeaderHeight !== listHeaderHeight) {
      Taro.getSystemInfo({
        success: res => {
          this.setState({
            height: res.windowHeight - getWebRealPx(listHeaderHeight)
          })
        }
      })
    }
  }

  isScrolling = false

  status = LIST_PAGE_STATUS.LOADING

  renderListHeader = () => {
    const { ListHeaderComponent } = this.props
    if (!ListHeaderComponent) return null

    if (typeof ListHeaderComponent === 'object') {
      return ListHeaderComponent
    }
    return ListHeaderComponent()
  };

  renderListContent = () => {
    const { data } = this.props
    return Array.isArray(data) && data.map(this.renderItemComponent)
  }

  renderItemComponent = (item, index) => {
    const { renderItem } = this.props
    return renderItem(item, index)
  }

  renderListFooter = () => {
    const {
      data, canLoadMore, loading, ListFooterComponent
    } = this.props
    if (data?.length === 0) {
      return null
    }
    if ((loading && canLoadMore) || (data?.length === 0 && loading)) {
      this.status = LIST_PAGE_STATUS.LOADING
    } else if (!loading && !canLoadMore) {
      this.status = LIST_PAGE_STATUS.FINISH
    }
    if (ListFooterComponent) {
      return ListFooterComponent(this.status)
    }
    return <CommonListFooter status={TEXT_MAP[this.status]} />
  }

  onEndReached = () => {
    const { onEndReached, canLoadMore } = this.props
    if (this.isScrolling || !onEndReached) { return }
    this.isScrolling = true
    canLoadMore && onEndReached()
    this.isScrolling = false
  }

  onRefresh = () => {
    const { onRefresh } = this.props
    this.status = LIST_PAGE_STATUS.LOADING
    onRefresh && onRefresh()
  }

  renderEmpty = () => {
    const { height } = this.state
    const { ListEmptyComponent, listEmptyTitle } = this.props
    if (typeof ListEmptyComponent === 'object') {
      return ListEmptyComponent
    }
    return ListEmptyComponent?.(height, listEmptyTitle)
  };

  render() {
    const { height } = this.state
    const { FootEmptyComponent } = this.props
    const {
      refreshing, refresherBackground, refresherDefaultStyle, refresherEnabled,
      backgroundColor, style, data, loading, showEmpty, showFooter, commonListContainer,
      contentClassName, scrollY = true
    } = this.props
    if (Array.isArray(data) && data.length === 0 && !loading && showEmpty) {
      return this.renderEmpty()
    }
    return (
      <ScrollView
        scrollY={scrollY}
        showScrollbar={false}
        onScrollToLower={this.onEndReached}
        lowerThreshold={100} // 自定义下拉刷新阈值
        onRefresherRefresh={this.onRefresh} // 自定义刷新函数
        refresherTriggered={refreshing} // 下拉刷新状态，true表示下拉熟悉已经被触发
        refresherEnabled={refresherEnabled} // 是否自定义下拉刷新
        refresherBackground={refresherBackground} // 设置自定义下拉刷新区域背景颜色
        refresherDefaultStyle={refresherDefaultStyle} // 设置自定义下拉刷新默认样式
        style={{ height: convertPx(height), backgroundColor, ...style }}
        className={commonListContainer}
      >
        <View className={contentClassName}>
          {this.renderListHeader()}
          {this.renderListContent()}
          {showFooter && this.renderListFooter()}
          {FootEmptyComponent && FootEmptyComponent()}
        </View>
      </ScrollView>
    )
  }
}

CommonList.propTypes = {
  renderItem: PropTypes.func.isRequired,
  data: PropTypes.array.isRequired,
  ListFooterComponent: PropTypes.func,

  refresherEnabled: PropTypes.bool,
  refresherBackground: PropTypes.string,
  refresherDefaultStyle: PropTypes.string,
  backgroundColor: PropTypes.string,
  style: PropTypes.object,
  listHeaderHeight: PropTypes.number,
  loading: PropTypes.bool,
  onEndReached: PropTypes.func,
  ListHeaderComponent: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.func
  ]),
  ListEmptyComponent: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.func
  ]),
  FootEmptyComponent: PropTypes.func,
  showEmpty: PropTypes.bool,
  showFooter: PropTypes.bool,
  contentClassName: PropTypes.string,
}

CommonList.defaultProps = {
  refresherEnabled: true,
  refresherBackground: '#f4f4f4',
  refresherDefaultStyle: 'black',
  backgroundColor: '#f4f4f4',
  style: {},
  listHeaderHeight: 0,
  loading: true,
  onEndReached: () => {},
  ListHeaderComponent: () => {},
  // eslint-disable-next-line react/display-name
  ListEmptyComponent: (height, title) => <NoContentEmpty title={title} containerStyle={getStyle(height)} />,
  showEmpty: true,
  showFooter: true,
  contentClassName: '',
}

const ListFooter = ({ status }) => (
  <View className="commonList-footer-container">
    <Text className="commonList-footer-text">{status}</Text>
  </View>
)

ListFooter.propTypes = {
  status: PropTypes.string
}

export default CommonList
export const CommonListFooter = React.memo(ListFooter)
